<?php
include_once BXD_INCLUDEPATH . 'core/baseEntity/TableItem.php';

/**
 * Componente per la creazione di una TABELLA
 *
 * @author Damiano Ciarla
 */
class Table
{
	private $popoList			= null;			//--> Array di oggetti sul quale stampare la tabella
	
	private $item				= array();		//--> Array dei campi da visualizzare nella tabella
	private $action				= array();

	private $styleClass			= "default";	//--> Stile css che si vuole applicare alla tabella. Se vuoto viene impostato 'default'
	private $tableName			= null;			//--> Nome della tabella !! DEVE ESSERE UNIVOCO NELLA PAGINA !!
	private $tableWidth			= "100%";		//--> Lunghezza della tabella

	private $reloadController	= null;			//--> Controller contenente la action che aggiorna la tabella
	private $reloadAction		= null;			//--> Action da chiamare quando si eseguono le operazioni di reload e paginazione

	private $loadAjaxFirstData	= false;		//--> Controllo se la tabella al primio utilizzo deve essere caricata in AJAX o meno
	private $pagination			= null;			//--> Utilizzata per controllare se viene usata paginazione o meno

	/**
	 * Inizializzazione dei parametri di default per il componente TABELLA.
	 *
	 * @param string $tableName			Nome della tabella
	 * @param array	$popoList			Array di Entity dal quale prendere i dati
	 * @param string $width				Larghezza della tabella
	 * @param string $styleClass		Stile della tabella
	 * @param string $realodController	Controller da chiamare (per aggiornare la tabella in AJAX) che contiene la action specificata nel parametro successivo
	 * @param string $realodAction		Action da chiamare per eseguire le operazioni di ricarica dati e paginazione
	 */

	public function __construct($tableName, $popoList, $width = null, $styleClass = null, $realodController = null, $realodAction = null)
	{
		$this->tableName	= $tableName;
		$this->popoList		= $popoList;

		if((is_int($width) && $width > 0) || (is_string($width) && $width == "100%")) $this->tableWidth	= $width;
		if(!is_null($styleClass) && is_string($styleClass)) $this->styleClass = $styleClass;
		
		if(!is_null($realodController) && is_string($realodController)) $this->reloadController	= $realodController;
		if(!is_null($realodAction) && is_string($realodAction)) $this->reloadAction	= $realodAction;
	}

	/**
	 * Imposta i dati da far stampare alla tabella. Questi ultimi dovranno essere passati
	 * sotto forma di un array di Entity
	 *
	 * @param array $popoList Array di Entity dal quale prendere i dati
	 */

	public function setPopoList($popoList)
	{
		$this->popoList = $popoList;
	}

	/**
	 * Imposta se il primo caricamento dei dati in tabella avviene in AJAX o
	 * prende i dati dalla response
	 *
	 * @param boolean $loadAjaxFirstData True o False
	 */

	public function setLoadAjaxFirstData($loadAjaxFirstData)
	{
		if(is_bool($loadAjaxFirstData)) $this->loadAjaxFirstData = $loadAjaxFirstData;
	}

	/**
	 * Aggiunge una colonna da visualizzare nella tabella
	 *
	 * @param string $item				Nome del parametro nella entity
	 * @param string $label				Intestazione della colonna
	 * @param int	 $width				Lunghezza della colonna
	 * @param string $renderCallback	Funzione di Collback
	 */

	public function addItem($item, $label, $width = null, $renderCallback = null)
	{
		$tableItem = new TableItem();

		$tableItem->setItem($item);
		$tableItem->setLabel($label);
		$tableItem->setWidth($width);
		$tableItem->setRenderCallback($renderCallback);

		$this->item[] = $tableItem;
	}

	/**
	 * Imposta lo style della tabella
	 *
	 * @param string $styleClass Nome dello style da associare alla tabella
	 */

	public function setStyleClass($styleClass = null)
	{
		if(is_null($styleClass))
		{
			$styleClass = "default";
		}
		
		$this->styleClass = $styleClass;
	}

	/**
	 * Imposta la lunghezza della tabella. E' possibile passare sia un valore
	 * assoluto sia una valore in percentuale ad es:
	 *
	 * setTableWidth("200")		->	Imposta la tabella con lunghezza 200px
	 * setTableWidth("100%")	->	Imposta che la tabella prende il 100% della
	 *								lunghezza
	 *
	 * @param string $tableWidth Lunghezza della tabella
	 */

	public function setTableWidth($tableWidth)
	{
		if((is_int($width) && $width > 0) || (is_string($width) && $width == "100%")) $this->tableWidth = $tableWidth;
	}

	public function setReloadController($reloadController)
	{
		if(!is_null($realodController) && is_string($realodController)) $this->reloadController = $reloadController;
	}

	public function setReloadAction($reloadAction)
	{
		if(!is_null($realodAction) && is_string($realodAction)) $this->reloadAction = $reloadAction;
	}

	/**
	 * Questo metodo si occupa di comporre e stampare la tabella e inoltre crea
	 * gli SCRIPT AJAX necessari per le funzioni di:
	 *
	 * RELOAD
	 * CAMBIO PAGINA
	 * CAMBIO NUMERO RIGHE DA VISUALIZZARE
	 */

	public function showTableAndScript()
	{
		if(!$this->loadAjaxFirstData and (!is_array($this->popoList) and !$this->popoList instanceof PaginationData ))
		{
			echo	"<font color='red'><strong>" .
					TD_("COMPONENTE TABELLA:", "components") .
					"</strong> " .
					TD_("È necessario impostare un array di oggetti per il valore <strong>'popoList'</strong> tramite il costruttore o il metodo <strong>'setPopoList'</strong>", "components") .
					"</font>";
			
			return;
		}

		if(!$this->loadAjaxFirstData)
		{
			$thead = $this->getHeadScript();
			$tbody = $this->getBodyScript();
			$tfoot = $this->getFootScript();

			$table = "<div id='content" . ucfirst($this->tableName) . "'>" . $thead . $tbody . $tfoot . "</div>";
		}
		else
		{
			$table  = "<div id='content" . ucfirst($this->tableName) . "'>";
			$table .= "<script type='text/javascript'>";
			$table .= "paginationTable" . ucfirst($this->tableName) . "(1, " . ROWSPAGE . ");";
			$table .= "</script>";
			$table .= "</div>";
		}

		$script = $this->getAjaxScript();

		echo $script . $table;
	}

	/**
	 * Questo metodo si occupa di comporre e stampare la tabella
	 * E' usato soprattuto come risposta AJAX nella paginazione. ES:
	 *
	 * Viene creata una view separata con il nome del '$realodAction' passato
	 * inizialmente nel costruttore della tabella. Questa nuova vista avrà un
	 * costruttore del tipo:
	 *
	 *			$table = new Table("list", $response->list, "100%");
	 *
	 * in modo tale che vengono solo stampati i dati della tabella senza ricreare
	 * gli script creati con la precedente funzione.
	 *
	 * Puo' essere usato inoltre per mostrare i dati di una lista di oggetti
	 * senza dover avere bisogno di script per le azioni sulla tabella
	 */

	public function showTableOnly()
	{
		if(!is_array($this->popoList) && !$this->popoList instanceof PaginationData)
		{
			echo	"<font color='red'><strong>" .
					TD_("COMPONENTE TABELLA:", "components") .
					"</strong> " .
					TD_("È necessario impostare un array di oggetti per il valore <strong>'popoList'</strong> tramite il costruttore o il metodo <strong>'setPopoList'</strong>", "components") .
					"</font>";

			return;
		}
		
		$thead = $this->getHeadScript();
		$tbody = $this->getBodyScript();
		$tfoot = $this->getFootScript();

		echo $thead . $tbody . $tfoot;
	}

	/*** -------------------- *** METODI INTERNI *** -------------------- ***/

	/**
	 * Questo metodo restituisce l'intestazione della tabella con i nome delle
	 * colonne prese dagli attributi valorizzati nell'array 'item'
	 *
	 * @return string Intestazione della tabella
	 */

	private function getHeadScript()
	{
		$thead  = "<table class='" . $this->styleClass . "' width='" . $this->tableWidth . "' cellspacing='1' cellpadding='0'>";
		$thead .= "<thead>";
		$thead .= "<tr>";

		foreach ($this->item as $item)
		{
			$width = $item->getWidth();

			if(!is_int($item->getWidth()) and !is_string($item->getWidth()))
				$width = "";

			$thead .= "<td width='" . $width . "'>" . ucfirst($item->getLabel()) . "</td>";
		}

		if(count($this->action) != 0)
			$thead .= "<td align='center'>Azioni</td>";

		$thead .= "</tr>";
		$thead .= "</thead>";

		return $thead;
	}

	/**
	 * Questo metodo ritorna il corpo della tabella ciclando l'array di oggetti
	 * 'popoList'. Se come ultimo elemento viene trovato un oggetto di istanza
	 * 'PaginationData' viene valorizzata la variabile 'pagination' con quest'ultimo
	 *
	 * @return string Corpo della tabella
	 */

	private function getBodyScript()
	{
		$tbody  = "<tbody>";

		$controlClass = 0;


		if($this->popoList instanceof PaginationData)
			$arrayObject = $this->popoList->getItems();
		else
			$arrayObject = $this->popoList;

		foreach ($arrayObject as $popoObj)
		{
			$classRow = "";

			if(($controlClass % 2) != 0) $classRow = "alternate";
			$controlClass++;

			$tbody .= "<tr class='" . $classRow . "'>";

			foreach ($this->item as $item)
			{
				if (is_null($item->getRenderCallback()))
				{
					$itemVal = "get" . $item->getItem();

					$result = $popoObj->$itemVal();

					if($result == "")
						$result = "&nbsp;";

					$tbody .= "<td>" . $result . "</td>";

				}
				else
				{
					$render = $item->getRenderCallback();
					$render->setObject($popoObj);

					$tbody .= "<td>" . $render->render() ."</td>";
				}
			}

			if(count($this->action) != 0)
				$tbody .= "<td align='center'>" . TD_("Azioni", "components") . "</td>";

			$tbody .= "</tr>";

			/*if(count($this->popoList) == 1)
			{
				$tbody .= "<tr>";
				$tbody .= "<td colspan='" . (count($this->item) + 1) . "'>" . TD_("Non è corretto assegnare ZERO o un valore inferiore come valore di paginazione. Riprovare con un valore superiore", "components") . "</td>";
				$tbody .= "</tr>";
			}*/

			//$this->pagination = $popoObj;
		}

		$tbody .= "</tbody>";

		return $tbody;
	}

	/**
	 * Questo metodo restituisce il FOOTER della Tabella controllando inizialmente
	 * se la variabile 'pagination' sia valorizzata o meno. In caso positivo
	 * vengono eseguite tutte le operazioni necessarie a calcolare i dati da
	 * passare alle funzioni JAVASCRIPT che is occupano di scorrere le pagine o
	 * ricreare una nuova tabella con una paginazione differente. In caso negativo
	 * viene stampato nel FOOTER soltanto il numero di elementi restituiti dalla
	 * query
	 *
	 * @return string Footer della tabella
	 */

	private function getFootScript()
	{
		$colspan = count($this->item);

		if(count($this->action) != 0)
			$colspan++;

		$tfoot  = "<tfoot>";
		$tfoot .= "<tr>";
		$tfoot .= "<td colspan='" . $colspan . "'>";

		if($this->popoList instanceof PaginationData)
		{
			$page		= $this->popoList->getPage();		//Pagina attuale
			$rowPage	= $this->popoList->getNumRows();	//Righe per pagina
			$numRows	= $this->popoList->getCountRows();	//Righe totali

			if($rowPage > 0)
				$maxPage = ceil($numRows/$rowPage);				//Pagina finale
			else
				$maxPage = 0;									//Pagina finale

			$tfoot .= "<div class='pagination'>";
			$tfoot .= "<div class='infoDataTable'>" . TD_("Risultati", "components") . ": <strong>[ " .  ((($page - 1) * $rowPage) + 1) . " - " . ((($page - 1) * $rowPage) + (count($this->popoList->getItems()) - 1)) . " ]</strong> su <strong>[ " . $numRows . " ]</strong></div>";
			$tfoot .= "<div class='selectNumRows'>";
			$tfoot .= "<form name='changeNumRows" . ucfirst($this->tableName) . "' action='javascript:changeNumRows" . ucfirst($this->tableName) . "()'>";
			$tfoot .= "<div class='buttonBox'><button type='submit' class='ui-state-default'><span class='ui-icon ui-icon-arrowrefresh-1-w'></span></button></div>";
			$tfoot .= "<div class='inputField'><input type='text' size='3' MAXLENGTH='10' value='" . $rowPage . "' /></div>";
			$tfoot .= "<div class='labelText'>" . TD_("Righe per pagina", "components") . "</div>";
			$tfoot .= "</form>";
			$tfoot .= "</div>";
			$tfoot .= "<div class='paginationDataTable'>";
			$tfoot .= "<div class='contentPagination'>";

			if ($page > 1)
			{
				$tfoot .= "<div class='butStart'><button class='ui-state-default' onclick='paginationTable" . ucfirst($this->tableName) . "(1, " . $rowPage . ")'><span class='ui-icon ui-icon-arrowthickstop-1-w'></span></button></div>";
				$tfoot .= "<div class='butPrev'><button class='ui-state-default' onclick='paginationTable" . ucfirst($this->tableName) . "(" . ($page - 1) . ", " . $rowPage . ")'><span class='ui-icon ui-icon-carat-1-w'></span></button></div>";
			}

			if ($page < $maxPage)
			{
				$tfoot .= "<div class='butEnd'><button class='ui-state-default' onclick='paginationTable" . ucfirst($this->tableName) . "(" . $maxPage .", " . $rowPage . ")'><span class='ui-icon ui-icon-arrowthickstop-1-e'></span></button></div>";
				$tfoot .= "<div class='butNext'><button class='ui-state-default'  onclick='paginationTable" . ucfirst($this->tableName) . "(" . ($page + 1) . ", " . $rowPage . ")'><span class='ui-icon ui-icon-carat-1-e'></span></button></div>";
			}

			$tfoot .= "<div class='nav'><div>" . $page . " di " . $maxPage . "</div></div>";

			$tfoot .= "</div>";
			$tfoot .= "</div>";
			$tfoot .= "</div>";

		}
		else
			$tfoot .= "<div align='center'>N&deg; Elementi in tabella: " . count($this->popoList) . "</div>";

		$tfoot .= "</td>";
		$tfoot .= "</tr>";
		$tfoot .= "</tfoot>";
		$tfoot .= "</table>";

		if($this->popoList instanceof PaginationData)
			$tfoot .= "<input type='hidden' name='currentPageOfPaging" . ucfirst($this->tableName) . "' id='currentPageOfPaging" . ucfirst($this->tableName) . "' value='" . $page . "' />";
		else
			$tfoot .= "<input type='hidden' name='currentPageOfPaging" . ucfirst($this->tableName) . "' id='currentPageOfPaging" . ucfirst($this->tableName) . "' value='' />";
		
		return $tfoot;
	}

	/**
	 * Questo metodo ritorna gli script necessari alla gestione della tabella:
	 *
	 * RELOAD
	 * PAGINATIONTABLE
	 * CHANGENUMROWS
	 *
	 * @return string Script per la gestione della Tabella
	 */

	private function getAjaxScript()
	{
		$script = "<script type='text/javascript'>";

		if(!is_null($this->reloadController) and !is_null($this->reloadAction))
		{
			$script .= "function reload" . ucfirst($this->tableName) . "()";
			$script .= "{";
			$script .= "var url = \"\";";
			$script .= "if($('input#currentPageOfPaging" . ucfirst($this->tableName) . "').val() != \"\")";
			$script .= "{";
			$script .= "url = \"/" . $this->reloadController . "/" . $this->reloadAction . "/\" + $('input#currentPageOfPaging" . ucfirst($this->tableName) . "').val() + \"/\" + $('form[name=changeNumRows" . ucfirst($this->tableName) . "] input:first').val() + \"." . BXD_EXT . "\";";
			$script .= "}";
			$script .= "else";
			$script .= "{";
			$script .= "url = \"/" . $this->reloadController . "/" . $this->reloadAction . "." . BXD_EXT . "\";";
			$script .= "}";
			$script .= "$('#content" . ucfirst($this->tableName) . "').load(url);";
			$script .= "}";
		}

		$script .= "function paginationTable" . ucfirst($this->tableName) . "(page, rowPage)";
		$script .= "{";
		$script .= "var url = \"/" . $this->reloadController . "/" . $this->reloadAction . "/\" + page + \"/\" + rowPage + \"." . BXD_EXT . "\";";
		$script .= "$(\"#content" . ucfirst($this->tableName) . "\").html(\"<div class='loading'>" . TD_("Attendere prego...", "components") . "</div>\").load(url);";
		$script .= "}";

		$script .= "function changeNumRows" . ucfirst($this->tableName) . "()";
		$script .= "{";
		$script .= "var newRowPage = $(\"form[name=changeNumRows" . ucfirst($this->tableName) . "] input:first\").val(); ";
		$script .= "var url = \"/" . $this->reloadController . "/" . $this->reloadAction . "/1/\" + newRowPage + \"." . BXD_EXT . "\";";
		$script .= "$(\"#content" . ucfirst($this->tableName) . "\").html(\"<div class='loading'>" . TD_("Attendere prego...", "components") . "</div>\").load(url);";
		$script .= "}";
		$script .= "</script>";

		return $script;
	}
}
?>